package com.marketlive.app.b2c.tiles;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.tiles.ComponentDefinition;
import org.apache.struts.tiles.Controller;
import org.apache.struts.tiles.DefinitionsFactoryException;
import org.apache.struts.tiles.NoSuchDefinitionException;
import org.apache.struts.tiles.xmlDefinition.I18nFactorySet;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.struts.ContextLoaderPlugIn;

public class SpringDelegatingDefinitionFactory extends I18nFactorySet
{
  private static final long serialVersionUID = -3326529995623419709L;
  private static Log log = LogFactory.getLog(SpringDelegatingDefinitionFactory.class);

  public ComponentDefinition getDefinition(String name, ServletRequest request, ServletContext servletContext)
    throws NoSuchDefinitionException, DefinitionsFactoryException
  {
    log.debug("getDefinition called with name: " + name);
    ComponentDefinition definition = super.getDefinition(name, request, servletContext);

    WebApplicationContext wac = getRequiredWebApplicationContext(servletContext);

    if (wac.containsBean(name)) {
      Object object = wac.getBean(name);

      if (!(object instanceof Controller)) {
        throw new RuntimeException("Bean '" + name + "' must implement Controller: " + object.getClass().getName());
      }

      log.info("Injecting Spring bean into tile controller: " + name);
      Controller controller = (Controller)object;
      definition.setControllerInstance(controller);
    }
    else {
      log.debug("No bean found with name: " + name + " in " + wac);
    }
    return definition;
  }

  public static WebApplicationContext getRequiredWebApplicationContext(ServletContext context)
  {
    String attrName = ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX;
    WebApplicationContext wac = (WebApplicationContext)context.getAttribute(attrName);

    if (wac == null) {
      throw new IllegalStateException("Could not find ContextLoaderPlugIn's WebApplicationContext as ServletContext attribute [" + attrName + "] - did you register [" + ContextLoaderPlugIn.class.getName() + "]?");
    }

    return wac;
  }
}